package br.com.mtg.movethegarbage.game;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import android.util.Log;
import br.com.mtg.movethegarbage.framework.Graphics;
import br.com.mtg.movethegarbage.graphics.SpriteManager;

public class Map
{
	Tile[][] tiles;
	int w, h;
	InputStream input;
	OutputStream output;
	float minX, minY;
	SpriteManager mapSpriteManager, backgroundSpriteManager;
	
	public Map(InputStream inputStream)
	{
		tiles = null;
		input = inputStream;
		try
		{
			read();
		}
		catch (Exception e)
		{
			Log.e("Map:", "Error reading/closing");
		}
	}

	public Map(Tile[][] _tiles, int _w, int _h, OutputStream outputStream)
	{
		w = _w;
		h = _h;
		tiles = _tiles;
		output = outputStream;

		if (outputStream != null)
		{
			try
			{
				write();
			}
			catch (Exception e)
			{
				Log.e("Map:", "Error writing/closing");
			}
		}
	}

	public Map(short[][] _tiles, int _w, int _h, OutputStream outputStream)
	{
		w = _w;
		h = _h;
		tiles = new Tile[w][h];
		int x, y;
		for (int i = 0; i < w * h; i++)
		{
			x = i % w;
			y = i / w;

			tiles[x][y] = new Tile(_tiles[x][y]);
		}
		output = outputStream;

		if (output != null)
		{
			try
			{
				write();
			}
			catch (Exception e)
			{
				Log.e("Map:", "Error writing/closing");
			}
		}
	}

	public void write() throws Exception
	{
		DataOutputStream dataOutput = new DataOutputStream(output);

		dataOutput.writeInt(w);
		dataOutput.writeInt(h);

		int x, y;

		for (int i = 0; i < w * h; i++)
		{
			x = i % w;
			y = i / w;

			dataOutput.writeShort(tiles[x][y].getTileID());
		}

		dataOutput.close();
	}

	public void read() throws Exception
	{
		DataInputStream dataInput = new DataInputStream(input);

		w = dataInput.readInt();
		h = dataInput.readInt();

		tiles = new Tile[w][h];
		int x, y;

		for (int i = 0; i < w * h; i++)
		{
			x = i % w;
			y = i / w;

			tiles[x][y] = new Tile(dataInput.readShort());
		}

		dataInput.close();
	}

	public void initializeMap(GameWorld world)
	{
		int x = 0;
		int y = 0;
		int thirdLvl, secondLvl, firstLvl;
		for (int i = 0; i < w * h; i++)
		{
			x = i % w;
			y = i / w;

			firstLvl = tiles[x][y].getTileID() % 10;
			secondLvl = (tiles[x][y].getTileID() - firstLvl) / 10;
			secondLvl = secondLvl % 10;
			thirdLvl = (tiles[x][y].getTileID() - secondLvl * 10 - firstLvl) / 100;

			if (secondLvl != 0)
			{
				Bin bin = new Bin(x * Tile.TILE_SIZE, y * Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE);
				bin.setSprite(Tile.getSprite((short) secondLvl));
				bin.mapMoveTo(x, y);
				bin.moveTo(x * Tile.TILE_SIZE + minX, y * Tile.TILE_SIZE + minY);
				world.instanceBin(bin);
			}

			if (thirdLvl != 0)
			{
				if (thirdLvl == Tile.PLAYER)
				{
					Player player = new Player(0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE);
					player.setSprite(Assets.SPRITE_PLAYER_UP);
					player.mapMoveTo(x, y);
					player.moveTo(x * Tile.TILE_SIZE + minX, y * Tile.TILE_SIZE + minY);
					world.instancePlayer(player);
				}
				else
				{
					Box box = new Box(0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE);
					box.setSprite(Tile.getSprite((short) thirdLvl));
					box.mapMoveTo(x, y);
					box.moveTo(x * Tile.TILE_SIZE + minX, y * Tile.TILE_SIZE + minY);
					world.instanceBox(box);
				}
			}

			tiles[x][y] = new Tile((short) firstLvl);
		}
	}
	
	public void initializeSpriteManagers(Graphics graphics)
	{
		int backgroundW = (int) (graphics.getWidth()/Tile.TILE_SIZE) + 1;
		int backgroundH = (int) (graphics.getHeight()/Tile.TILE_SIZE) + 1;
		
		backgroundSpriteManager = new SpriteManager(graphics, backgroundW*backgroundH);
		mapSpriteManager = new SpriteManager(graphics, w * h);
	}

	public void draw(Graphics graphics)
	{
		int backgroundW = (int) (graphics.getWidth()/Tile.TILE_SIZE) + 1;
		int backgroundH = (int) (graphics.getHeight()/Tile.TILE_SIZE) + 1;

		int x, y;
		
		backgroundSpriteManager.beginDraw(Assets.tex_sprites);
		for (int i = 0; i < backgroundW*backgroundH; i++)
		{
			x = i % backgroundW;
			y = i / backgroundW;

			backgroundSpriteManager.drawSprite(x * Tile.TILE_SIZE, y * Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.TILE_SIZE, Assets.SPRITE_GRASS);
		}
		backgroundSpriteManager.endDraw();

		mapSpriteManager.beginDraw(Assets.tex_sprites);

		for (int i = 0; i < w * h; i++)
		{
			x = i % w;
			y = i / w;

			mapSpriteManager.drawSprite(x * Tile.TILE_SIZE + minX, y * Tile.TILE_SIZE + minY, Tile.TILE_SIZE, Tile.TILE_SIZE, Tile.getSprite(tiles[x][y]));
		}

		mapSpriteManager.endDraw();
	}
}
